from django.conf import settings
from urllib.parse import urlencode, parse_qs
from urllib.request import urlopen
from itsdangerous import TimedJSONWebSignatureSerializer, BadData
from . import constants
import logging
import json


logger = logging.getLogger("django")


class OAuthQQException(Exception):
    def __str__(self):
        return "QQ服务器返回数据异常"


class OAuthQQ(object):
    """QQ登录工具类"""
    def __init__(self, client_id=None, redirect_uri=None, state=None, client_secret=None):
        self.client_id = client_id or settings.QQ_CLIENT_ID
        self.redirect_uri = redirect_uri or settings.QQ_REDIRECT_URI
        self.state = state or settings.QQ_STATE
        self.client_secret = client_secret or settings.QQ_CLIENT_SECRET

    # 获取qq登录页面
    def get_qq_login_url(self):
        query_params = {
            "response_type": "code",
            "client_id": self.client_id,
            "redirect_uri": self.redirect_uri,
            "state": self.state,
        }
        query_str = urlencode(query_params)
        url = "https://graph.qq.com/oauth2.0/authorize" + "?" + query_str
        return url

    # 获取access_token
    def get_access_token(self, code):
        query_params = {
            "grant_type": "authorization_code",
            "client_id": self.client_id,
            "client_secret": self.client_secret,
            "code": code,
            "redirect_uri": self.redirect_uri
        }
        query_str = urlencode(query_params)
        url = "https://graph.qq.com/oauth2.0/token" + "?" + query_str

        response = urlopen(url)
        response_data = response.read().decode()
        response_data = parse_qs(response_data)
        access_token = response_data.get("access_token")
        if not access_token:
            logger.error("code:%s, msg:%s" % (response_data["code"], response_data["msg"]))
            raise OAuthQQException
        # print(access_token)
        return access_token[0]

    def get_openid(self, token):
        url = "https://graph.qq.com/oauth2.0/me?" + ("access_token=%s" % token)
        # callback( {"client_id": "YOUR_APPID", "openid": "YOUR_OPENID"} );\n
        response = urlopen(url)
        response_data = response.read().decode()
        response_dict = json.loads(response_data[10:-4])
        openid = response_dict.get("openid")
        # print(openid)
        if not openid:
            logger.error("code:%s, msg:%s" % (response_dict["code"], response_dict["msg"]))
            raise OAuthQQException
        return openid

    @staticmethod
    def generate_qq_user_token(openid):
        serializer = TimedJSONWebSignatureSerializer(settings.SECRET_KEY, constants.SAVE_QQ_USER_TOKEN_EXPIRES)
        token = serializer.dumps({"openid": openid}).decode()
        return token

    @staticmethod
    def check_qq_user_token(token):
        serializer = TimedJSONWebSignatureSerializer(settings.SECRET_KEY, constants.SAVE_QQ_USER_TOKEN_EXPIRES)
        try:
            token_dict = serializer.loads(token)
        except BadData:
            return None
        openid = token_dict.get("openid")
        return openid
